package com.imooc.activitiweb.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.imooc.activitiweb.constants.Constants;
import com.imooc.activitiweb.mapper.ProMapper;
import com.imooc.activitiweb.pojo.JmEnclosure;
import com.imooc.activitiweb.pojo.Project;
import com.imooc.activitiweb.util.AjaxResponse;
import com.imooc.activitiweb.util.GlobalConfig;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.bpmn.model.*;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import com.imooc.activitiweb.util.BpmnUtil;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.SequenceFlow;
@RestController
@RequestMapping("/pro")
public class ProController {

    @Autowired
    ProMapper proMapper;

    @Autowired
    private TaskRuntime taskRuntime;

    @Autowired
    private TaskService taskService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private ProcessRuntime processRuntime;

    @Autowired
    HistoryService historyService;

    @Value("${jm.file.root.path}")
    private String fileRootPath;

    /**
     * 项目列表
     * @param pageNum
     * @param pageSize
     * @return
     */
    @GetMapping("/getPros")
    public AjaxResponse getPros(@RequestParam(value = "pageNum",defaultValue = "0") Integer pageNum,
                                @RequestParam(value = "pageSize",defaultValue = "10") Integer pageSize,
                                @RequestParam(value = "proNum" ,required = false) String proNum,
                                @RequestParam(value = "enterpriseName" ,required = false) String enterpriseName,
                                @RequestParam(value = "proName" ,required = false) String proName,
                                @RequestParam(value = "createTime" ,required = false) String createTime
//                                @RequestParam(value = "createTime" ,required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date createTime
                                ) {

        PageHelper.startPage(pageNum, pageSize);
        HashMap hashMap=new HashMap();
        if(StringUtils.isNotBlank(proNum)){
            hashMap.put("proNum",proNum);
        }
        if(StringUtils.isNotBlank(enterpriseName)){
            hashMap.put("enterpriseName",enterpriseName);
        }
        if(StringUtils.isNotBlank(proName)){
            hashMap.put("proName",proName);
        }
        if(StringUtils.isNotBlank(createTime)){
            hashMap.put("createTime",createTime);
        }

        List<Project> allOrderPresent = proMapper.selectJmPro(hashMap);
        PageInfo pageInfo=new PageInfo(allOrderPresent);
        pageInfo.setList(allOrderPresent);
        return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), pageInfo);
    }

    /**
     * 根据ID获取项目
     */
    @GetMapping("/getProById")
    public AjaxResponse getProById(@RequestParam(value = "id") String id) {
        HashMap hashMap=new HashMap();
        hashMap.put("id",id);
        Project jmPro = proMapper.selectJmProById(hashMap);
        return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                GlobalConfig.ResponseCode.SUCCESS.getDesc(), jmPro);
    }

    @GetMapping("/checkUser")
    public AjaxResponse checkUser() {
        String userName=SecurityContextHolder.getContext().getAuthentication().getName();
        if (StringUtils.isBlank(userName)||userName.equals("anonymousUser")) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    GlobalConfig.ResponseCode.ERROR.getDesc(), "未登录");
        } else if (!Constants.USERlIST.contains(userName)) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    GlobalConfig.ResponseCode.ERROR.getDesc(), "您没有操作权限");
        }
        return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                GlobalConfig.ResponseCode.SUCCESS.getDesc(), null);
    }

    @PostMapping("/addPro")
    public AjaxResponse addPro(@RequestBody Project project) {
        int res=0;
        String userName=SecurityContextHolder.getContext().getAuthentication().getName();
        if (StringUtils.isBlank(userName)||userName.equals("anonymousUser")) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    GlobalConfig.ResponseCode.ERROR.getDesc(), "未登录");
        } else if (!Constants.USERlIST.contains(userName)) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    GlobalConfig.ResponseCode.ERROR.getDesc(), "您没有操作权限");
        }
        if(StringUtils.isNotBlank(project.getId())){
            project.setUpdateBy(userName);
            res=proMapper.updatePro(project);
        }else{
            project.setCreateBy(userName);
            project.setId(IdUtil.simpleUUID());
            res=proMapper.savePro(project);
        }

        if(res==1){
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), null);
        }else{
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    GlobalConfig.ResponseCode.ERROR.getDesc(), null);
        }

    }

    @GetMapping("/delPro")
    public AjaxResponse delPro(@RequestParam("id") String id) {
        String userName=SecurityContextHolder.getContext().getAuthentication().getName();
        if (StringUtils.isBlank(userName)||userName.equals("anonymousUser")) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    GlobalConfig.ResponseCode.ERROR.getDesc(), "未登录");
        } else if (!Constants.USERlIST.contains(userName)) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    GlobalConfig.ResponseCode.ERROR.getDesc(), "您没有操作权限");
        }
        int res=proMapper.delPro(id);
        if(res==1){
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), null);
        }else{
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    GlobalConfig.ResponseCode.ERROR.getDesc(), null);
        }

    }


    /**
     * excel导入工具类
     * @return 返回数据集合
     * @throws IOException
     */
    @PostMapping("/uploadPro")
    public AjaxResponse uploadPro(@RequestParam("file") MultipartFile multipartFile) throws IOException {
        String userName=SecurityContextHolder.getContext().getAuthentication().getName();
        if (StringUtils.isBlank(userName)||userName.equals("anonymousUser")) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    GlobalConfig.ResponseCode.ERROR.getDesc(), "未登录");
        } else if (!Constants.USERlIST.contains(userName)) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    GlobalConfig.ResponseCode.ERROR.getDesc(), "您没有操作权限");
        }
        String fileName = multipartFile.getOriginalFilename();
        // 上传文件为空
        if (StringUtils.isEmpty(fileName)) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "没有导入文件", fileName);
        }
        //上传文件大小为1000条数据
        if (multipartFile.getSize() > 1024 * 1024 * 300) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "上传失败: 文件大小不能超过300M!", fileName);
        }
        // 上传文件名格式不正确
        if (fileName.lastIndexOf(".") != -1 && !".xlsx".equals(fileName.substring(fileName.lastIndexOf(".")))) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "文件名格式不正确, 请使用后缀名为.XLSX的文件", fileName);
        }
        File file = convert(multipartFile);
        ExcelReader reader = ExcelUtil.getReader(file);
        List<Map<String,Object>> readAll = reader.readAll();

        //将数据封装到list<Map>中
        List<Map<String, Object>> dataList = new ArrayList<>();
        List<Project> projectList = new ArrayList<>();
        for (int i = 0; i < readAll.size(); i++) {

            if (null != readAll.get(i)) {
                String typesPro = readAll.get(i).get("项目类型").toString();
                String proNum = readAll.get(i).get("项目编号").toString();
                String enterpriseName = readAll.get(i).get("企业（单位）名称").toString();
                String area = readAll.get(i).get("所属区县").toString();
                String proName = readAll.get(i).get("项目名称").toString();
                String proType = readAll.get(i).get("项目类别").toString();//项目类别
                String filingDept = readAll.get(i).get("备案部门").toString();
                String contractAmount = readAll.get(i).get("2020年实际投资额").toString();
                String plannedCompletionTime = readAll.get(i).get("计划完成时间").toString();
                String concacts = readAll.get(i).get("联系人").toString();
                String phone = readAll.get(i).get("电话").toString();


                Project pro=new Project();
                pro.setId(IdUtil.simpleUUID());
                pro.setTypesPro(typesPro);
                pro.setProNum(proNum);
                pro.setEnterpriseName(enterpriseName);
                pro.setArea(area);
                pro.setProName(proName);
                pro.setProType(proType);
                pro.setFilingDept(filingDept);
                pro.setContractAmount(contractAmount);
                pro.setPlannedCompletionTime(plannedCompletionTime);
                pro.setConcacts(concacts);
                pro.setPhone(phone);
                projectList.add(pro);
//                Map<String, Object> hashMap = new HashMap<>();
//                for (int j = 0; j < columNames.length; j++) {
//                    Object property = readAll.get(i).get(j);
//                    hashMap.put(columNames[j], property);
//                }
//                dataList.add(hashMap);
            }
        }

        if(projectList.size()>0){
            proMapper.batchSavePro(projectList);
        }
        return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                GlobalConfig.ResponseCode.SUCCESS.getDesc(), dataList);
    }

    public File convert(MultipartFile file) throws IOException {
        File convFile = new File(file.getOriginalFilename());
        convFile.createNewFile();
        FileOutputStream fos = new FileOutputStream(convFile);
        fos.write(file.getBytes());
        fos.close();
        return convFile;
    }

    /**
     *
     * @param multipartFile
     * @return
     * @throws IOException
     */
    @PostMapping("/uploadFile")
    public AjaxResponse uploadFile(@RequestParam("file") MultipartFile[] multipartFile,
                                   @RequestParam("taskID") String taskID) throws IOException {
        String userName=SecurityContextHolder.getContext().getAuthentication().getName();
        if (StringUtils.isBlank(userName)||userName.equals("anonymousUser")) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    GlobalConfig.ResponseCode.ERROR.getDesc(), "未登录");
        }
        Task task = taskRuntime.task(taskID);
        HashMap<String, Object> stringObjectHashMap = proMapper.queryPageIndexByTaskName(task.getName());
        String filePath = "";
        File f = new File(fileRootPath);
        if(!f.exists()){
            f.mkdirs();
        }
        // 多文件上传
        for (MultipartFile file : multipartFile){
            String str = (new SimpleDateFormat("yyyyMMddHHmmssSSS")).format(new Date());
            String originalFilename = file.getOriginalFilename();
            filePath = new StringBuilder(fileRootPath)
                   // .append(System.currentTimeMillis())
                    .append(str)
                    .append(originalFilename)
                    .toString();
            file.transferTo(new File(filePath));
            JmEnclosure jmEnclosure=new JmEnclosure();

            jmEnclosure.setId(IdUtil.simpleUUID());
            jmEnclosure.setName(originalFilename);
            jmEnclosure.setUpload_address(filePath);
            jmEnclosure.setPROC_DEF_ID_(task.getProcessDefinitionId());
            jmEnclosure.setPROC_INST_ID_(task.getProcessInstanceId());
//            jmEnclosure.setFORM_KEY_(task.getFormKey());
            jmEnclosure.setNode_id(stringObjectHashMap.get("id").toString());
            jmEnclosure.setUpload_by(SecurityContextHolder.getContext().getAuthentication().getName());
//            jmEnclosure.setDeclareNum();
            proMapper.insertJmEnclosure(jmEnclosure);
        }
        return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                GlobalConfig.ResponseCode.SUCCESS.getDesc(), filePath);
    }

    @GetMapping("/deleteJmEnclosure")
    public AjaxResponse deleteJmEnclosure(@RequestParam("id") String id) throws IOException {
        JmEnclosure jmEnclosure = proMapper.queryFileById(id);
        String uploadAddress = jmEnclosure.getUpload_address();
        proMapper.deleteFileById(id);

        File f = new File(uploadAddress);
        if(f.exists()){
            f.delete();
        }
        return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                GlobalConfig.ResponseCode.SUCCESS.getDesc(), null);
    }

    @GetMapping("/queryJmDeclareByTaskID")
    public AjaxResponse queryJmDeclareByTaskID(@RequestParam("taskID") String taskID) throws IOException {
        Map map=new HashMap();

        Task task = taskRuntime.task(taskID);

        Map declare = proMapper.queryJmDeclareByProcessInstanceId(task.getProcessInstanceId());


        String key=processRuntime.processInstance(task.getProcessInstanceId()).getProcessDefinitionKey();
        map.put("processDefinitionKey",key);


        List<JmEnclosure> list = proMapper.queryJmEnclosureByProcessInstanceIdAndFormKey(task.getProcessInstanceId(), task.getName());
        List<Project> allOrderPresent = proMapper.selectJmProRes(task.getProcessInstanceId());
        map.put("declare",declare);
        map.put("allOrderPresent",allOrderPresent);
        map.put("step2",list.stream().filter(s->s.getNode_id().equals("2")).collect(Collectors.toList()));
        map.put("step3",list.stream().filter(s->s.getNode_id().equals("3")).collect(Collectors.toList()));
        map.put("step4",list.stream().filter(s->s.getNode_id().equals("4")).collect(Collectors.toList()));
        map.put("step5",list.stream().filter(s->s.getNode_id().equals("5")).collect(Collectors.toList()));
        map.put("step6",list.stream().filter(s->s.getNode_id().equals("6")).collect(Collectors.toList()));
        map.put("step7_1",list.stream().filter(s->s.getNode_id().equals("7")&&s.getUpload_by().equals("ghxtc")).collect(Collectors.toList()));
        map.put("step7_2",list.stream().filter(s->s.getNode_id().equals("7")&&s.getUpload_by().equals("jgdw")).collect(Collectors.toList()));
        map.put("step8",list.stream().filter(s->s.getNode_id().equals("8")).collect(Collectors.toList()));


        map.put("step9_1",list.stream().filter(s->s.getNode_id().equals("9")&&s.getUpload_by().equals("ghxtc")).collect(Collectors.toList()));
        map.put("step9_2",list.stream().filter(s->s.getNode_id().equals("9")&&s.getUpload_by().equals("jgdw")).collect(Collectors.toList()));

        map.put("step10_1",list.stream().filter(s->s.getNode_id().equals("10")&&s.getUpload_by().equals("gfgykjc")).collect(Collectors.toList()));
        map.put("step10_2",list.stream().filter(s->s.getNode_id().equals("10")&&s.getUpload_by().equals("jgdw")).collect(Collectors.toList()));
        map.put("step11",list.stream().filter(s->s.getNode_id().equals("11")).collect(Collectors.toList()));

        map.put("step12_1",list.stream().filter(s->s.getNode_id().equals("12")&&s.getUpload_by().equals("gfgykjc")).collect(Collectors.toList()));
        map.put("step12_2",list.stream().filter(s->s.getNode_id().equals("12")&&s.getUpload_by().equals("jgdw")).collect(Collectors.toList()));
        map.put("step13",list.stream().filter(s->s.getNode_id().equals("13")).collect(Collectors.toList()));
        map.put("step14",list.stream().filter(s->s.getNode_id().equals("14")).collect(Collectors.toList()));
        map.put("step15",list.stream().filter(s->s.getNode_id().equals("15")).collect(Collectors.toList()));

        map.put("step16_1",list.stream().filter(s->s.getNode_id().equals("16")&&s.getUpload_by().equals("gfgykjc")).collect(Collectors.toList()));
        map.put("step16_2",list.stream().filter(s->s.getNode_id().equals("16")&&s.getUpload_by().equals("msc")).collect(Collectors.toList()));
        map.put("step17_1",list.stream().filter(s->s.getNode_id().equals("17")&&s.getUpload_by().equals("gfgykjc")).collect(Collectors.toList()));
        map.put("step17_2",list.stream().filter(s->s.getNode_id().equals("17")&&s.getUpload_by().equals("jgdw")).collect(Collectors.toList()));
        map.put("step18_1",list.stream().filter(s->s.getNode_id().equals("18")&&s.getUpload_by().equals("ghxtc")).collect(Collectors.toList()));
        map.put("step18_2",list.stream().filter(s->s.getNode_id().equals("18")&&s.getUpload_by().equals("gfgykjc")).collect(Collectors.toList()));

        return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                GlobalConfig.ResponseCode.SUCCESS.getDesc(), map);
    }

    @GetMapping("/queryJmDeclareByProcessInstanceID")
    public AjaxResponse queryJmDeclareByProcessInstanceID(@RequestParam("processInstanceID") String processInstanceID) throws IOException {
        Map map=new HashMap();
        Map declare = proMapper.queryJmDeclareByProcessInstanceId(processInstanceID);

        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceID).singleResult();

        String key=historicProcessInstance.getProcessDefinitionKey();
        map.put("processDefinitionKey",key);

        List<JmEnclosure> list = proMapper.queryJmEnclosureByProcessInstanceIdAndFormKey(processInstanceID, null);
        List<Project> allOrderPresent = proMapper.selectJmProRes(processInstanceID);
        map.put("declare",declare);
        map.put("allOrderPresent",allOrderPresent);
        map.put("step2",list.stream().filter(s->s.getNode_id().equals("2")).collect(Collectors.toList()));
        map.put("step3",list.stream().filter(s->s.getNode_id().equals("3")).collect(Collectors.toList()));
        map.put("step4",list.stream().filter(s->s.getNode_id().equals("4")).collect(Collectors.toList()));
        map.put("step5",list.stream().filter(s->s.getNode_id().equals("5")).collect(Collectors.toList()));
        map.put("step6",list.stream().filter(s->s.getNode_id().equals("6")).collect(Collectors.toList()));
        map.put("step7_1",list.stream().filter(s->s.getNode_id().equals("7")&&s.getUpload_by().equals("ghxtc")).collect(Collectors.toList()));
        map.put("step7_2",list.stream().filter(s->s.getNode_id().equals("7")&&s.getUpload_by().equals("jgdw")).collect(Collectors.toList()));
        map.put("step8",list.stream().filter(s->s.getNode_id().equals("8")).collect(Collectors.toList()));


        map.put("step9_1",list.stream().filter(s->s.getNode_id().equals("9")&&s.getUpload_by().equals("ghxtc")).collect(Collectors.toList()));
        map.put("step9_2",list.stream().filter(s->s.getNode_id().equals("9")&&s.getUpload_by().equals("jgdw")).collect(Collectors.toList()));

        map.put("step10_1",list.stream().filter(s->s.getNode_id().equals("10")&&s.getUpload_by().equals("gfgykjc")).collect(Collectors.toList()));
        map.put("step10_2",list.stream().filter(s->s.getNode_id().equals("10")&&s.getUpload_by().equals("jgdw")).collect(Collectors.toList()));
        map.put("step11",list.stream().filter(s->s.getNode_id().equals("11")).collect(Collectors.toList()));

        map.put("step12_1",list.stream().filter(s->s.getNode_id().equals("12")&&s.getUpload_by().equals("gfgykjc")).collect(Collectors.toList()));
        map.put("step12_2",list.stream().filter(s->s.getNode_id().equals("12")&&s.getUpload_by().equals("jgdw")).collect(Collectors.toList()));
        map.put("step13",list.stream().filter(s->s.getNode_id().equals("13")).collect(Collectors.toList()));
        map.put("step14",list.stream().filter(s->s.getNode_id().equals("14")).collect(Collectors.toList()));
        map.put("step15",list.stream().filter(s->s.getNode_id().equals("15")).collect(Collectors.toList()));

        map.put("step16_1",list.stream().filter(s->s.getNode_id().equals("16")&&s.getUpload_by().equals("gfgykjc")).collect(Collectors.toList()));
        map.put("step16_2",list.stream().filter(s->s.getNode_id().equals("16")&&s.getUpload_by().equals("msc")).collect(Collectors.toList()));
        map.put("step17_1",list.stream().filter(s->s.getNode_id().equals("17")&&s.getUpload_by().equals("gfgykjc")).collect(Collectors.toList()));
        map.put("step17_2",list.stream().filter(s->s.getNode_id().equals("17")&&s.getUpload_by().equals("jgdw")).collect(Collectors.toList()));
        map.put("step18_1",list.stream().filter(s->s.getNode_id().equals("18")&&s.getUpload_by().equals("ghxtc")).collect(Collectors.toList()));
        map.put("step18_2",list.stream().filter(s->s.getNode_id().equals("18")&&s.getUpload_by().equals("gfgykjc")).collect(Collectors.toList()));

        return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                GlobalConfig.ResponseCode.SUCCESS.getDesc(), map);
    }

    @GetMapping("/queryPageIndexByTaskID")
    public AjaxResponse queryPageIndexByTaskID(@RequestParam("taskID") String taskID) {
        Task task = taskRuntime.task(taskID);
        return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                GlobalConfig.ResponseCode.SUCCESS.getDesc(), proMapper.queryPageIndexByTaskName(task.getName()));
    }

    @GetMapping("/getProcessInstanceByTaskID")
    public AjaxResponse getProcessInstanceByTaskID(@RequestParam("taskID") String taskID) {
        Task task = taskRuntime.task(taskID);
        ProcessInstance processInstance = processRuntime.processInstance(task.getProcessInstanceId());
        return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                GlobalConfig.ResponseCode.SUCCESS.getDesc(), processInstance);
    }

    @GetMapping(value = "/downLoad",produces = "application/json;charset=UTF-8")
    public void downLoad(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String id=request.getParameter("id");
        JmEnclosure jmEnclosure = proMapper.queryFileById(id);
        String uploadPath=jmEnclosure.getUpload_address();
        File file=new File(uploadPath);

        //获取最后一个.的位置
        int lastIndexOf = uploadPath.lastIndexOf(".");
        //获取文件的后缀名 .jpg
        String suffix = uploadPath.substring(lastIndexOf);

        request.setCharacterEncoding("utf-8");
        // 文件存储路径
        String path = fileRootPath;

        // 从请求中获取文件名
        String fileName = request.getParameter("fileName");

        // 创建输出流对象
        ServletOutputStream outputStream = response.getOutputStream();

        //以字节数组的形式读取文件
        byte[] bytes = FileUtil.readBytes(uploadPath);

        // 设置返回内容格式
        response.setContentType("application/octet-stream");

        // 把文件名按UTF-8取出并按ISO8859-1编码，保证弹出窗口中的文件名中文不乱码
        // 中文不要太多，最多支持17个中文，因为header有150个字节限制。
        // 这一步一定要在读取文件之后进行，否则文件名会乱码，找不到文件
        fileName = new String(fileName.getBytes("UTF-8"),"ISO8859-1");

        // 设置下载弹窗的文件名和格式（文件名要包括名字和文件格式）
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName+suffix);


        // 返回数据到输出流对象中
        outputStream.write(bytes);

        // 关闭流对象
        IoUtil.close(outputStream);

    }



    @PostMapping("/uploadProRes")
    public AjaxResponse uploadProRes(@RequestParam("file") MultipartFile multipartFile,@RequestParam("taskID") String taskID) throws IOException {
        String userName=SecurityContextHolder.getContext().getAuthentication().getName();
        if (StringUtils.isBlank(userName)||userName.equals("anonymousUser")) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    GlobalConfig.ResponseCode.ERROR.getDesc(), "未登录");
        }
        Task task = taskRuntime.task(taskID);
        String fileName = multipartFile.getOriginalFilename();
        // 上传文件为空
        if (StringUtils.isEmpty(fileName)) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "没有导入文件", fileName);
        }
        //上传文件大小为1000条数据
        if (multipartFile.getSize() > 1024 * 1024 * 300) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "上传失败: 文件大小不能超过300M!", fileName);
        }
        // 上传文件名格式不正确
        if (fileName.lastIndexOf(".") != -1 && !".xlsx".equals(fileName.substring(fileName.lastIndexOf(".")))) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "文件名格式不正确, 请使用后缀名为.XLSX的文件", fileName);
        }
        File file = convert(multipartFile);
        ExcelReader reader = ExcelUtil.getReader(file);
        List<Map<String,Object>> readAll = reader.readAll();
        List<Project> allOrderPresent = proMapper.selectJmPro(new HashMap());
        //将数据封装到list<Map>中
        List<Map<String, Object>> dataList = new ArrayList<>();
        List<Project> projectList = new ArrayList<>();
        for (int i = 0; i < readAll.size(); i++) {

            if (null != readAll.get(i)) {
                String typesPro = readAll.get(i).get("项目类型").toString();
                String enterpriseName = readAll.get(i).get("企业（单位）名称").toString();
                String area = readAll.get(i).get("所属区县").toString();
                String proType = readAll.get(i).get("项目类别").toString();//项目类别
                String filingDept = readAll.get(i).get("备案部门").toString();
                String contractAmount = readAll.get(i).get("2020年实际投资额").toString();
                String plannedCompletionTime = readAll.get(i).get("计划完成时间").toString();
                String concacts = readAll.get(i).get("联系人").toString();
                String phone = readAll.get(i).get("电话").toString();

                String proNum = readAll.get(i).get("项目编号").toString();
                String proName = readAll.get(i).get("项目名称").toString();

                for(int j=0;j<allOrderPresent.size();j++){
                    Project project = allOrderPresent.get(j);
                    if(proNum.equals(project.getProNum())&&proName.equals(project.getProName())){
                        Project pro=new Project();
                        pro.setId(IdUtil.simpleUUID());
                        pro.setTypesPro(typesPro);
                        pro.setProNum(proNum);
                        pro.setEnterpriseName(enterpriseName);
                        pro.setArea(area);
                        pro.setProName(proName);
                        pro.setProType(proType);
                        pro.setFilingDept(filingDept);
                        pro.setContractAmount(contractAmount);
                        pro.setPlannedCompletionTime(plannedCompletionTime);
                        pro.setConcacts(concacts);
                        pro.setPhone(phone);

                        pro.setPROC_DEF_ID_(task.getProcessDefinitionId());
                        pro.setPROC_INST_ID_(task.getProcessInstanceId());
                        projectList.add(pro);
                    }
                }

//                Map<String, Object> hashMap = new HashMap<>();
//                for (int j = 0; j < columNames.length; j++) {
//                    Object property = readAll.get(i).get(j);
//                    hashMap.put(columNames[j], property);
//                }
//                dataList.add(hashMap);
            }
        }

        if(projectList.size()>0){
            proMapper.batchSaveProRes(projectList);
        }
        return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                GlobalConfig.ResponseCode.SUCCESS.getDesc(), dataList);
    }



    /**
     * 申报列表
     * @param pageNum
     * @param pageSize
     * @return
     */
    @GetMapping("/getDeclare")
    public AjaxResponse getDeclare(@RequestParam(value = "pageNum",defaultValue = "0") Integer pageNum,
                                @RequestParam(value = "pageSize",defaultValue = "10") Integer pageSize,
                                @RequestParam(value = "declare_num" ,required = false) String declare_num,
                                @RequestParam(value = "declaration_time" ,required = false) String declaration_time
    ) {

        PageHelper.startPage(pageNum, pageSize);
        HashMap hashMap=new HashMap();
        if(StringUtils.isNotBlank(declare_num)){
            hashMap.put("declare_num",declare_num);
        }
        if(StringUtils.isNotBlank(declaration_time)){
            hashMap.put("declaration_time",declaration_time);
        }

        List<Map> allOrderPresent = proMapper.getDeclareList(hashMap);
        for(Map map:allOrderPresent){
            List<org.activiti.engine.task.Task> tasks = taskService.
                    createTaskQuery().processInstanceId(map.get("PROC_INST_ID_").toString()).list();

            if(tasks!=null && tasks.size()>0){
                map.put("finishStatus","进行中");
            }else{
                map.put("finishStatus","已完成");
            }
        }
        PageInfo pageInfo=new PageInfo(allOrderPresent);
        pageInfo.setList(allOrderPresent);



        return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                GlobalConfig.ResponseCode.SUCCESS.getDesc(), pageInfo);
    }



    @PostMapping("/reject")
    public AjaxResponse reject(@RequestParam("taskId") String taskId,@RequestParam("rejectComment") String rejectComment) {
        List<Map<String, String>> incomeNodes = new ArrayList<>();

        org.activiti.engine.task.Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        String currActivityId = task.getTaskDefinitionKey();

        // 获取当前用户任务节点
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        Process process = bpmnModel.getProcesses().get(0);

        getIncomeNodesRecur(currActivityId, incomeNodes, process, false);

        FlowNode currFlow = (FlowNode)bpmnModel.getMainProcess().getFlowElement(currActivityId);
        if (currFlow == null) {
            List<SubProcess> subProcessList = bpmnModel.getMainProcess().findFlowElementsOfType(SubProcess.class, true);
            for (SubProcess subProcess : subProcessList) {
                FlowElement flowElement = subProcess.getFlowElement(currActivityId);

                if (flowElement != null) {
                    currFlow = (FlowNode) flowElement;
                    break;
                }
            }
        }

        // 记录原活动方向
        List<SequenceFlow> oriSequenceFlows = Lists.newArrayList();
        oriSequenceFlows.addAll(currFlow.getOutgoingFlows());

        // 清理活动方向
        currFlow.getOutgoingFlows().clear();

        List<SequenceFlow> newSequenceFlows = Lists.newArrayList();

        for (int i = 0; i< incomeNodes.size(); i++) {
            Map<String, String> item = incomeNodes.get(i);
            String nodeId = item.get("id");

            // 获取目标节点
            FlowNode target = (FlowNode)bpmnModel.getFlowElement(nodeId);

            //如果不是同一个流程（子流程）不能驳回
            if (!(currFlow.getParentContainer().equals(target.getParentContainer()))) {
                continue;
            }

            // 建立新方向
            SequenceFlow newSequenceFlow = new SequenceFlow();
            String uuid = UUID.randomUUID().toString().replace("-","");
            newSequenceFlow.setId(uuid);
            newSequenceFlow.setSourceFlowElement(currFlow);// 原节点
            newSequenceFlow.setTargetFlowElement(target);// 目标节点
            newSequenceFlows.add(newSequenceFlow);
        };

        currFlow.setOutgoingFlows(newSequenceFlows);

        SimpleDateFormat sf=new SimpleDateFormat();
        String format = sf.format(new Date());
        // 拒接、通过、驳回指定节点
        taskService.addComment(task.getId(), task.getProcessInstanceId(), rejectComment);
        taskService.complete(taskId);



        //恢复原方向
        currFlow.setOutgoingFlows(oriSequenceFlows);

        return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                GlobalConfig.ResponseCode.SUCCESS.getDesc(), null);
    }
    /**
     * 递归遍历获取上个任务节点
     **/
    public void getIncomeNodesRecur(String currentNodeId, List<Map<String, String>> incomeNodes, org.activiti.bpmn.model.Process process, boolean isAll) {
        FlowElement currentFlowElement = process.getFlowElement(currentNodeId);
        List<SequenceFlow> incomingFlows = null;
        if (currentFlowElement instanceof UserTask) {
            incomingFlows = ((UserTask) currentFlowElement).getIncomingFlows();
        } else if (currentFlowElement instanceof Gateway) {
            incomingFlows = ((Gateway) currentFlowElement).getIncomingFlows();
        } else if (currentFlowElement instanceof StartEvent) {
            incomingFlows = ((StartEvent) currentFlowElement).getIncomingFlows();
        }
        if (incomingFlows != null && incomingFlows.size() > 0) {
            incomingFlows.forEach(incomingFlow -> {
                String expression = incomingFlow.getConditionExpression();
                // 出线的上一节点
                String sourceFlowElementID = incomingFlow.getSourceRef();
                // 查询上一节点的信息
                FlowElement preFlowElement = process.getFlowElement(sourceFlowElementID);

                //用户任务
                if (preFlowElement instanceof UserTask) {
                    Map<String,String> tempMap = new HashMap<>();
                    tempMap.put("id", preFlowElement.getId());
                    tempMap.put("name", preFlowElement.getName());
                    incomeNodes.add(tempMap);
                    if (isAll) {
                        getIncomeNodesRecur(preFlowElement.getId(), incomeNodes, process, true);
                    }
                }
                //排他网关
                else if (preFlowElement instanceof ExclusiveGateway) {
                    getIncomeNodesRecur(preFlowElement.getId(), incomeNodes, process, isAll);
                }
                //并行网关
                else if (preFlowElement instanceof ParallelGateway) {
                    getIncomeNodesRecur(preFlowElement.getId(), incomeNodes, process, isAll);
                }
            });
        }
    }

}
